home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 March: Reference Library / Dev.CD Mar 96 RL / Dev.CD Mar 96 RL.toast / Technical Documentation / develop / develop Issue 25 / develop Issue 25 code / ToolFrontEnd / ToolFrontEnd Source / ToolFrontEnd Compiler / ToolFrontEnd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-20  |  11.4 KB  |  459 lines  |  [TEXT/CWIE]

  1. #define OLDROUTINENAMES 1
  2.  
  3. /* standard headers */
  4. #include <ctype.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7.  
  8. /* system headers */
  9. #include <Gestalt.h>
  10. #include <LowMem.h>
  11. #include <Strings.h>
  12. #include <TextUtils.h>
  13. #include <CodeFragments.h>
  14. #include <Resources.h>
  15. #include <MixedMode.h>
  16.  
  17. /* compiler headers */
  18. #include <A4Stuff.h>
  19. #include <DropInCompiler.h>
  20.  
  21. /* project headers */
  22. #include "ToolFrontEnd.h"
  23. #include "ToolServer.h"
  24. #include "FullPath.h"
  25.  
  26.  
  27.  
  28. /* prototypes of local functions */
  29. static OSErr    Compile(ToolFrontEndStatus* status);
  30. static OSErr    ProcessFile(ToolFrontEndStatus* status, ToolFrontEndPref **prefs,
  31.                             short currentExtension);
  32.  
  33.  
  34. // mixed mode info for include file scanners
  35. enum
  36. {
  37.     uppScannerEntryPointInfo = kPascalStackBased
  38.          | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  39.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ToolFrontEndStatus*)))
  40. };
  41.  
  42.  
  43. /*
  44.  *    main    -    main entry-point for ToolFrontEnd Tool
  45.  *
  46.  */
  47.  
  48. pascal short main(CompilerParameterBlockPtr cpb)
  49. {
  50.     short                    result;
  51.     ToolFrontEndStatus*        status;
  52.     OSErr                    err;
  53.     
  54.     /* set up global world (68K only) */
  55.     EnterCodeResource();
  56.     
  57.     result = noErr;
  58.     
  59.     /* dispatch on compiler request */
  60.     switch (cpb->request)
  61.     {
  62.     case reqInitCompiler:
  63.         /* compiler has just been loaded into memory */
  64.         break;
  65.         
  66.     case reqTermCompiler:
  67.         /* compiler is about to be unloaded from memory */
  68.         break;
  69.         
  70.     case reqCompile:
  71.         /* compile a source file */
  72.         status = (ToolFrontEndStatus*)NewPtrClear(sizeof(ToolFrontEndStatus));
  73.         err = MemError();
  74.         if (err == noErr)
  75.         {
  76.             int i;
  77.             status->cpb = cpb;
  78.             err = Compile(status);
  79.             for (i = 0; i < status->numFolderPaths; i++)
  80.                 DisposeHandle(status->folderPaths[i].path);
  81.             DisposePtr((Ptr)status);
  82.         }
  83.         result = (err == noErr);
  84.         break;
  85.         
  86.     default:
  87.         result = paramErr;
  88.         break;
  89.     }
  90.     
  91.     /* tear down global world (68K only) */
  92.     ExitCodeResource();
  93.     
  94.     /* return result code */
  95.     return (result);
  96. }
  97.  
  98.  
  99. static OSErr    Compile(ToolFrontEndStatus* status)
  100. {
  101.     Handle                prefsHand;
  102.     ToolFrontEndPref**    prefs;
  103.     OSErr                err;
  104.     short                currentExtension;
  105.     
  106.     /* Load in our prefs. */
  107.     err = CWCompGetPreferences(status->cpb, kToolFrontEndPanelName, &prefsHand);
  108.     if (err != noErr) return err;
  109.     prefs = (ToolFrontEndPrefHandle)prefsHand;
  110.     
  111.     status->linecount = 0;
  112.     
  113.     // find the extension of this file
  114.     {
  115.         Str15 extension;
  116.         int i;
  117.         Byte state;
  118.         
  119.         for (i = status->cpb->sourcefile.name[0]; i > 0 && status->cpb->sourcefile.name[i] != '.'; i--)
  120.             ;
  121.         if (i < 0) return paramErr;
  122.         extension[0] = status->cpb->sourcefile.name[0] - (i - 1);
  123.         BlockMoveData(status->cpb->sourcefile.name + i, extension + 1, extension[0]);
  124.         
  125.         state = HGetState((Handle)prefs);
  126.         HLock((Handle)prefs);
  127.         for (i = 0, currentExtension = -1; i < (*prefs)->numExtensions; i++)
  128.         {
  129.             if (EqualString(extension, (*prefs)->extensions[i].extension, false, true))
  130.             {
  131.                 currentExtension = i;
  132.                 break;
  133.             }
  134.         }
  135.         HSetState((Handle)prefs, state);
  136.         if (currentExtension == -1) return paramErr;
  137.     }
  138.     
  139.     // process include files
  140.     if ((*prefs)->extensions[currentExtension].scanner[0] != 0)
  141.     {
  142.         err = ProcessFile(status, prefs, currentExtension);
  143.     }
  144.     
  145.     // now build the ToolServer command
  146.     {
  147.         Handle commandHandle = NewHandle(0);
  148.         AEDesc command;
  149.         CStringHandle output = NULL, diagnostic = NULL;
  150.         Str31 nameStem;
  151.         
  152.         // parameterize the ToolServer command line
  153.         
  154.         if (status->numFolderPaths > 0)
  155.         {
  156.             // add the IncludeFiles variable
  157.             int i;
  158.  
  159.             PtrAndHand("Set IncludeFiles \'", commandHandle, sizeof("Set IncludeFiles \'") - 1);
  160.             for (i = 0; i < status->numFolderPaths; i++)
  161.             {
  162.                 char space = ' ', quote = '\"';
  163.                 Byte state;
  164.                 
  165.                 state = HGetState((Handle)prefs);
  166.                 HLock((Handle)prefs);
  167.                 PtrAndHand((*prefs)->extensions[currentExtension].includeFileArg + 1,
  168.                             commandHandle, (*prefs)->extensions[currentExtension].includeFileArg[0]);
  169.                 HSetState((Handle)prefs, state);
  170.                 PtrAndHand(&space, commandHandle, 1);
  171.                 PtrAndHand("e, commandHandle, 1);
  172.                 HandAndHand(status->folderPaths[i].path, commandHandle);
  173.                 PtrAndHand("e, commandHandle, 1);
  174.                 PtrAndHand(&space, commandHandle, 1);
  175.             }
  176.             PtrAndHand("\'; ", commandHandle, sizeof("\'; ") - 1);
  177.         }
  178.         
  179.         // add the SourceFile variable -- XXX -- if not saved, use temp file instead!
  180.         {
  181.             Handle fileName;
  182.             short fileNameSize;
  183.             
  184.             PtrAndHand("Set SourceFile \'", commandHandle, sizeof("Set SourceFile \'") - 1);
  185.             err = FSpGetFullPath(&status->cpb->sourcefile, &fileNameSize, &fileName);
  186.             if (err == noErr)
  187.             {
  188.                 HandAndHand(fileName, commandHandle);
  189.                 DisposeHandle(fileName);
  190.                 PtrAndHand("\'; ", commandHandle, sizeof("\'; ") - 1);
  191.             }
  192.         }
  193.     
  194.         // add the SourceFileStem variable
  195.         if (err == noErr)
  196.         {
  197.             int i;
  198.             
  199.             BlockMoveData(status->cpb->sourcefile.name, nameStem, status->cpb->sourcefile.name[0] + 1);
  200.             for (i = nameStem[0]; i > 0; i--)
  201.             {
  202.                 if (nameStem[i] == '.')
  203.                 {
  204.                     nameStem[0] = i - 1;
  205.                     break;
  206.                 }
  207.             }
  208.             
  209.             PtrAndHand("Set SourceFileStem \'", commandHandle, sizeof("Set SourceFileStem \'") - 1);
  210.             PtrAndHand(nameStem + 1, commandHandle, nameStem[0]);
  211.             PtrAndHand("\'; ", commandHandle, sizeof("\'; ") - 1);
  212.         }
  213.         
  214.         // add the Directory command to go to the project folder
  215.         if (err == noErr)
  216.         {
  217.             short dirNameLength;
  218.             Handle dirName;
  219.             
  220.             err = GetFullPath(status->cpb->targetfile.vRefNum, status->cpb->targetfile.parID, NULL, &dirNameLength, &dirName);
  221.             
  222.             if (err == noErr)
  223.             {
  224.                 PtrAndHand("Directory \'", commandHandle, sizeof("Directory \'") - 1);
  225.                 HandAndHand(dirName, commandHandle);
  226.                 PtrAndHand("\'; ", commandHandle, sizeof("\'; ") - 1);
  227.                 DisposeHandle(dirName);
  228.             }
  229.         }
  230.         
  231.         // add the Execute command for the script include file, if any
  232.         if ((err == noErr) && (*prefs)->scriptIncludeFile[0] != 0)
  233.         {
  234.             Str31 includeFileName;
  235.             FSSpec includeSpec;
  236.             Boolean alreadyincluded;
  237.             Handle hand = NULL;
  238.             long size;
  239.             
  240.             Byte state = HGetState((Handle)prefs);
  241.             HLock((Handle)prefs);
  242.             BlockMoveData((*prefs)->scriptIncludeFile, includeFileName,
  243.                           (*prefs)->scriptIncludeFile[0] + 1);
  244.             HSetState((Handle)prefs, state);
  245.             
  246.             err = CWCompFindIncludeFile(status->cpb, includeFileName, true, &hand, &size,
  247.                                         &includeSpec, &alreadyincluded, false);
  248.             if (err == noErr)
  249.             {
  250.                 short incNameLength;
  251.                 Handle incName;
  252.                 
  253.                 if (hand != NULL)
  254.                 {
  255.                     // XXX -- file is open in IDE window -- use temp file
  256.                     CWCompErrorMessage(status->cpb, "The script file is open -- close it first!");
  257.                     DisposeHandle(hand);
  258.                     err = paramErr;
  259.                 }
  260.                 
  261.                 if (err == noErr)
  262.                     err = FSpGetFullPath(&includeSpec, &incNameLength, &incName);
  263.                 
  264.                 if (err == noErr)
  265.                 {
  266.                     PtrAndHand("Execute \'", commandHandle, sizeof("Execute \'") - 1);
  267.                     HandAndHand(incName, commandHandle);
  268.                     PtrAndHand("\'; ", commandHandle, sizeof("\'; ") - 1);
  269.                     DisposeHandle(incName);
  270.                 }
  271.             }
  272.         }
  273.  
  274.         // add the template command line from prefs
  275.         if (err == noErr)
  276.         {
  277.             Byte state = HGetState((Handle)prefs);
  278.             HLock((Handle)prefs);
  279.             PtrAndHand((*prefs)->extensions[currentExtension].commandTemplate + 1, commandHandle,
  280.                         (*prefs)->extensions[currentExtension].commandTemplate[0]);
  281.             HSetState((Handle)prefs, state);
  282.         }
  283.  
  284.         // make the ToolServer command        
  285.         if (err == noErr)
  286.         {
  287.             HLock(commandHandle);
  288.             command.descriptorType = typeNull;
  289.             command.dataHandle = NULL;
  290.             err = AECreateList(NULL, 0, false, &command);
  291.             if (err == noErr)
  292.                 err = AEPutPtr(&command, 0, typeChar, *commandHandle, GetHandleSize(commandHandle));
  293.         }
  294.         DisposeHandle(commandHandle);
  295.         
  296.         if (err == noErr)
  297.         {
  298.             // send the ToolServer command
  299.             err = ToolServerCommand(&command, &output, &diagnostic, NULL, NULL);
  300.             AEDisposeDesc(&command);
  301.         
  302.             // show number of lines processed
  303.             CWCompDisplayLines(status->cpb, status->linecount);
  304.  
  305.             // display any diagnostic result
  306.             if (err != noErr)
  307.             {
  308.                 if (diagnostic != NULL)
  309.                 {
  310.                     char null = 0;
  311.                     PtrAndHand(&null, (Handle)diagnostic, 1);
  312.                     HLock((Handle)diagnostic);
  313.                     CWCompErrorMessage(status->cpb, (const char*)*diagnostic);
  314.                 }
  315.                 else
  316.                 {
  317.                     CWCompOSErrorMessage(status->cpb, "ToolServer error. ", err);
  318.                 }
  319.             }
  320. #if 0
  321.             else
  322.             {
  323.                 // XXX test code for a future version
  324.                 FSSpec testSpec;
  325.                 unsigned long time;
  326.                 Handle path;
  327.                 short len;
  328.                 char c;
  329.                 
  330.                 testSpec.vRefNum = status->cpb->targetfile.vRefNum;
  331.                 testSpec.parID = status->cpb->targetfile.parID;
  332.                 BlockMoveData(nameStem, testSpec.name, nameStem[0] + 1);
  333.                 BlockMoveData(".xh", testSpec.name + nameStem[0] + 1, 3);
  334.                 testSpec.name[0] += 3;
  335.                 err = FSpGetFullPath(&testSpec, &len, &path);
  336.                 if (err != noErr) DebugStr("\pgoldarnit!");
  337.                 c = 0;
  338.                 PtrAndHand(&c, path, 1);
  339.                 HLock(path);
  340.                 err = CWCompGetPrecompiledHeaderSpec(status->cpb, &testSpec, (char*)*path);
  341.                 if (err != noErr) DebugStr("\pfug!");
  342.                 GetDateTime(&time);
  343.                 CWCompSetModDate(status->cpb, &testSpec, time);
  344.                 //if (err != noErr) DebugStr("\pscheiss!");
  345.             }
  346. #endif
  347.         }
  348.         if (output != NULL) DisposeHandle((Handle)output);
  349.         if (diagnostic != NULL) DisposeHandle((Handle)diagnostic);
  350.     }
  351.     
  352.     return err;
  353. }
  354.  
  355.  
  356. static OSErr    ProcessFile(ToolFrontEndStatus* status, ToolFrontEndPref** prefs,
  357.                             short currentExtension)
  358. {
  359.     OSErr err;
  360.     FCBPBRec pb;
  361.     FSSpec spec;
  362.     CInfoPBRec ci;
  363. #if GENERATINGCFM
  364.     long response;
  365. #endif
  366.     
  367.     // find the scanner folder and file
  368.     pb.ioFCBIndx = 0; // use ioRefNum
  369.     pb.ioRefNum = LMGetCurApRefNum();
  370.     pb.ioNamePtr = NULL;
  371.     err = PBGetFCBInfoSync(&pb);
  372.     if (err != noErr) return err;
  373.     GetIndString(spec.name, 129, 1); // CodeWarrior Plugins
  374.     ci.dirInfo.ioNamePtr = spec.name;
  375.     ci.dirInfo.ioVRefNum = pb.ioFCBVRefNum;
  376.     ci.dirInfo.ioDrDirID = pb.ioFCBParID;
  377.     ci.dirInfo.ioFDirIndex = 0;
  378.     err = PBGetCatInfoSync(&ci);
  379.     if (err != noErr) return err;
  380.     GetIndString(spec.name, 129, 2); // Include Scanners
  381.     ci.dirInfo.ioNamePtr = spec.name;
  382.     ci.dirInfo.ioVRefNum = pb.ioFCBVRefNum;
  383.     ci.dirInfo.ioDrDirID = ci.dirInfo.ioDrDirID;
  384.     ci.dirInfo.ioFDirIndex = 0;
  385.     err = PBGetCatInfoSync(&ci);
  386.     if (err != noErr) return err;
  387.     spec.vRefNum = pb.ioFCBVRefNum;
  388.     spec.parID = ci.dirInfo.ioDrDirID;
  389.     BlockMoveData((*prefs)->extensions[currentExtension].scanner, spec.name,
  390.                     (*prefs)->extensions[currentExtension].scanner[0] + 1);
  391.  
  392. #if GENERATINGCFM
  393.     // if on PowerPC...
  394.     err = Gestalt(gestaltSysArchitecture, &response);
  395.     if (err == noErr && response == gestaltPowerPC)
  396.     {
  397.         // load code fragment
  398.         CFragConnectionID connID;
  399.         Str255 errName;
  400.         UniversalProcPtr newRoutine = 0;
  401.         Ptr mainAddr;
  402.  
  403.         err = GetDiskFragment(&spec, 0, kWholeFork, NULL, kLoadNewCopy, &connID, &mainAddr,
  404.                                 errName);
  405.         if (err != noErr) return err;
  406.         
  407.         // call main entry point
  408.         newRoutine = NewRoutineDescriptor((ProcPtr)mainAddr, uppScannerEntryPointInfo, GetCurrentArchitecture());
  409.         if (newRoutine == NULL)
  410.         {
  411.             err = MemError();
  412.             CloseConnection(&connID);
  413.             return err;
  414.         }
  415.         err = CallUniversalProc(newRoutine, uppScannerEntryPointInfo, status);
  416.         
  417.         // unload code fragment
  418.         CloseConnection(&connID);
  419.     }
  420.     else // 68K
  421. #endif
  422.     {
  423.         Handle h;
  424.         pascal OSErr (*f)(ToolFrontEndStatus* status);
  425.         short refNum;
  426.         
  427.         // open resource file
  428.         refNum = FSpOpenResFile(&spec, fsRdPerm);
  429.         if (refNum < 0) return ResError();
  430.         
  431.         // load code resource
  432.         h = Get1Resource('Scan', 128);
  433.         if (h == 0)
  434.         {
  435.             CloseResFile(refNum);
  436.             return resNotFound;
  437.         }
  438.         
  439.         // call main entry point
  440.         HNoPurge(h);
  441.         HLock(h);
  442.         f = (pascal OSErr (*)(ToolFrontEndStatus* status))(*h);
  443.         err = (*f)(status);
  444.         
  445.         // close resource file
  446.         CloseResFile(refNum);
  447.     }
  448.     
  449.     if (err != noErr)
  450.     {
  451.         Str31 s;
  452.         NumToString(err, s);
  453.         p2cstr(s);
  454.         CWCompErrorMessage(status->cpb, (char*)s);
  455.     }
  456.     
  457.     return err;
  458. }
  459.